home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 102_01.zip / STONE.C < prev    next >
Text File  |  1993-06-03  |  13KB  |  441 lines

  1. /*
  2.             ===
  3.     "STONE" --- H19  Version (for H19/Z19/H89/Z89 ONLY)
  4.             ===
  5.  
  6.     (otherwise known as "Awari")
  7.  
  8.     This version written by:
  9.  
  10.     Terry Hayes & Clark Baker
  11.     Real-Time Systems Group
  12.     MIT Lab for Computer Science
  13.  
  14.     Hacked up a little by Leor Zolman and Steve Ward
  15.     (Steve did all the neat H19 display hackery!)
  16.  
  17.     The algorithm used for STONE is a common one
  18.     to Artificial Intelligence people: the "Alpha-
  19.     Beta" pruning heuristic. By searching up and down 
  20.     a tree of possible moves and keeping record of
  21.     the minimum and maximum scores from the
  22.     terminal static evaluations, it becomes possible
  23.     to pinpoint move variations which can in no way
  24.     affect the outcome of the search. Thus, those
  25.     variations can be simply discarded, saving 
  26.     expensive static evaluation time.
  27.  
  28.     THIS is the kind of program that lets C show its
  29.     stuff; Powerful expression operators and recursion
  30.     combine to let a powerful algorithm be implemented
  31.     painlessly.
  32.  
  33.     And it's fun to play!
  34.  
  35.  
  36.     Rules of the game:
  37.  
  38.     Each player has six pits in front of him and a
  39.     "home" pit on one side (the computer's home pit
  40.     is on the left; your home pit is on the right.)
  41.  
  42.     At the start of the game, all pits except the home
  43.     pits are filled with n stones, where n can be anything
  44.     from 1 to 6.
  45.  
  46.     To make a move, a player picks one of the six pits
  47.     on his side of the board that has stones in it, and
  48.     redistributes the stones one-by-one going counter-
  49.     clockwise around the board, starting with the pit
  50.     following the one picked. The opponent's HOME pit is
  51.     never deposited into.
  52.  
  53.     If the LAST stone happens to fall in that player's
  54.     home pit, he moves again.
  55.  
  56.     If the LAST stone falls into an empty pit on the
  57.     moving player's side of  board, then any stones in the
  58.     pit OPPOSITE to that go into the moving
  59.     player's home pit.
  60.  
  61.     When either player clears the six pits on his
  62.     side of the board, the game is over. The other player
  63.     takes all stones in his six pits and places them in
  64.     his home pit. Then, the player with the most stones
  65.     in his home pit is the winner.
  66.  
  67.     The six pits on the human side are numbered one
  68.     to six from left to right; the six pits on the    
  69.     computer's side are numbered one to six right-to-
  70.     left.
  71.  
  72.     The standard game seems to be with three stones;
  73.     Less stones make it somewhat easier (for both you
  74.     AND the computer), while more stones complicate
  75.     the game. As far as difficulty goes, well...it
  76.     USED to be on a scale of 1 to 50, but I couldn't
  77.     win it at level 1. So I changed it to 1-300, and
  78.     couldn't win at level 1. So I changed it to 1-1000,
  79.     and if I STILL can't win it at level 1, I think
  80.     I'm gonna commit suicide.
  81.  
  82.     Good Luck!!!
  83. */
  84.  
  85. unsigned total;
  86. char string[80];
  87.  
  88. unsigned COUNT, Seed;
  89. int NUM;
  90.  
  91. int holex[14];
  92. int holey[14];
  93. int stonex[48];
  94. int stoney[48];
  95.  
  96. exinit()
  97.  {    initw(holex, "7,10,10,10,10,10,10,8,4,4,4,4,4,4");
  98.     initw(holey, "7,16,24,32,40,48,56,66,56,48,40,32,24,16");
  99.     initw(stonex, "0,0,0,-1,1,1,1,-1,-1,1,1,0,0,-1,-1,-2,-2,-2,-2,\
  100.      -2,-3,-3,-3,-3,-3,-1,0,-2,1,-3,2,2,2,2,3,3,-4,-4,-4,-4,3,2,3,\
  101.      2,3,3,-4,-4");
  102.     initw(stoney, "0,1,-1,0,0,-1,1,-1,1,-2,2,-2,2,-2,2,0,-1,1,-2,2,\
  103.      0,-1,1,-2,2,-3,-3,-3,-3,-3,0,-1,-2,1,0,-1,-1,0,-2,1,1,2,-2,-3,\
  104.      2,-3,2,-3");
  105.  }
  106.  
  107. putchar(ch)
  108.  {    
  109.     bios(4,ch);
  110.  }
  111.  
  112. dance(y, x)
  113.  {    int i,j,k,l;
  114.     k = 30;
  115.     puts("\033q\033F");
  116.     while (!bios(2))
  117.      { display(y,x);
  118.        for (i=0; i<k; i++) {
  119.         putchar((i+j) & 3? ' ':'^');
  120.         for (l = 0; l < 50; l++)
  121.             ;
  122.        }
  123.        j++; }
  124.  
  125.     display(y, x);
  126.     for (i=0; i<k; i++) putchar(' ');
  127.  }
  128.  
  129.  
  130. main(argc,argv)
  131. {
  132.         int  hum,com,y,inp;
  133.         char board[14];
  134.     for (y=0; y<1000; y++) Seed += stonex[y];
  135.     srand(Seed);
  136.     exinit();
  137.  
  138. new:    printf("\033E\033q\033G");
  139.     printf("New Game:\r\nDifficulty (1-1000, or q to quit): ");
  140.     inp = atoi(gets(string));
  141.     if (inp < 1) { printf("\033z"); return; }
  142.     if (inp>1000) goto new;
  143.     printf("Number of stones (1-6): ");
  144.     NUM = atoi(gets(string));
  145.     COUNT = inp * 65;
  146.     NewBD();
  147.     initb(board);
  148.     display(21,50); printf("\033p Difficulty: %d \033q", inp);
  149.     display(19,0);
  150.     printf("Do you want to go first (y or n)? ");
  151.     inp = toupper(getchar());
  152.         printf("\033l\n\n");
  153.         if (inp ==  'N') goto first;
  154.         y = 0;
  155.         while(notdone(board)) {
  156. again:        display(20,10);
  157.                 printf("\033G\033p Your move:   \b\b");
  158.                 for (;;) {
  159.             dance(20, 40); puts("\033p"); display(20,22);
  160.                         inp = getchar() - '0';
  161.             if (toupper(inp+'0')=='Q')goto new;
  162.                         if (inp < 1 || inp > 6 || !board[inp])
  163.              { putchar(7); goto again; }
  164.                         y++;
  165.                         break;
  166.                 }
  167.         puts("\033q");
  168.                 if (!dmove(board,inp)) continue;
  169. first:        display(20,10); rptc(' ', 30);
  170.                 y = 0;
  171.                 while (notdone(board)) {
  172.             display(21, 10);
  173.                     printf("\033p I'm thinking \033q");
  174.                         inp = comp(board);
  175.             display(21,10); rptc(' ', 30);
  176.             display(22,10);
  177.                         printf("\033p Computer moves: ");
  178.                         printf("%d \033q",inp-7);
  179.                         y++;
  180.                         if (dmove(board,inp)) break;
  181.             display(22,10); rptc(' ', 30);
  182.                 }
  183.                 y = 0;
  184.         }
  185.         com = board[0]; 
  186.         hum = board[7];
  187.         for (inp = 1; inp < 7; inp++) { 
  188.                 hum += board[inp]; 
  189.                 com += board[inp+7]; 
  190.         }
  191.     display(23,10);
  192.         printf("\033p Score:   me %d  you %d . . . ",com,hum);
  193.     if (com>hum) switch (rand() % 4) {
  194.         case 0: printf("Gotcha!!");
  195.             break;
  196.         case 1:    printf("Chalk one up for the good guys!");
  197.             break;
  198.         case 2: printf("Automation does it again!");
  199.             break;
  200.         case 3: printf("I LOVE to WIN!");
  201.         }
  202.     else if (hum==com) printf("How frustrating!!");
  203.     else printf("Big Deal! Try a REAL difficulty!");
  204.     printf(" \033q\033G");
  205.     display(19,0);
  206.     sleep(5);
  207.         printf("\033p New Game (y/n): \033q\033K");
  208.     dance(19,40);
  209.     if (toupper(getchar()) == 'Y') goto new;
  210.     display(23,0);
  211.     printf("\033z");
  212.         exit();
  213. }
  214.  
  215. mod(i,j)  int i,j; 
  216. {
  217.     ++i;
  218.         if (i == 7) return( j ? 7 : 8);
  219.         if (i > 13) return ( j ? 1 : 0);
  220.         return(i);
  221. }
  222.  
  223. initb(board)  char *board; 
  224. {
  225.          int i,j;
  226.         for (i= 0; i <14; ++i)
  227.      { board[i]=0;
  228.        if (i != 0 && i != 7) for (j = 0; j < NUM; j++) incpit(board,i); }
  229.         return;
  230. }
  231.  
  232. comp(board)  char *board; 
  233. {
  234.          int score;
  235.         int bestscore,best;
  236.         char temp[14];
  237.          int i;
  238.         unsigned nodes;
  239.         total = 0;
  240.  
  241.         if ((i = countnodes(board,8)) == 1)
  242.                 for (best = 8; best < 14; ++best)
  243.                         if (board[best]) return(best);
  244.         nodes = COUNT/i;
  245.         bestscore = -10000;
  246.         for (i = 13; i > 7; --i) if (board[i]) {
  247.                 score = mmove(board,temp,i);
  248.         score = comp1( temp, score, nodes, bestscore, 10000);
  249.                 if (score > bestscore) {
  250.                         bestscore = score;
  251.                         best = i;
  252.                 }
  253.         }
  254.     display(19,10);
  255.         if (bestscore > 1000)
  256.         puts("\033p I'VE GOT YOU! \033q\n");
  257.         if (bestscore < -1000)
  258.                 printf("\033p YOU'VE GOT ME! \033q\n");
  259.         return(best);
  260. }
  261.  
  262. comp1(board,who,count,alpha,beta)
  263.  char *board; int who; int alpha,beta;
  264. unsigned count; 
  265. {
  266.          int i;
  267.         int turn,new;
  268.         char temp[14];
  269.         unsigned nodes;
  270.         if (count < 1) {
  271.                 new = board[0]-board[7];
  272.                 for (i = 1; i < 7; ++i) { turn = min(7-i,board[i]);
  273.                                           new -= 2*turn - board[i]; }
  274.                 for (i = 8; i < 14; ++i) { turn = min(14-i,board[i]);
  275.                                            new += 2*turn - board[i]; }
  276.                 if (board[0] > 6*NUM) new += 1000;
  277.                 if (board[7] > 6*NUM) new -= 1000;
  278.                 return(new);
  279.         }
  280.         if (!notdone(board)) {
  281.                 new = board[0]+board[8]+board[9]+board[10]
  282.                     +board[11]+board[12]+board[13]-board[1]-board[2]
  283.                     -board[3]-board[4]-board[5]-board[6]-board[7];
  284.                 if ( new < 0) return (new - 1000);
  285.                 if ( new > 0) return (new + 1000);
  286.                 return(0);
  287.         }
  288.         nodes = count/countnodes(board,8-who*7);
  289.         for (i = 7*(1-who)+6; i > 7*(1-who); --i)
  290.                 if (board[i]) {
  291.                         turn = mmove(board,temp,i);
  292.                         new = comp1(temp,(turn? 1-who: who),nodes,alpha,beta);
  293.                         if (who) {
  294.                            beta = min(new,beta);
  295.                            if (beta <= alpha) return(beta); }
  296.                         else { 
  297.                             alpha = max(new,alpha);
  298.                             if (alpha >= beta) return(alpha); }
  299.                 }
  300.         return(who ? beta : alpha);
  301. }
  302.  
  303. min(i,j)  int i,j; 
  304. {
  305.         return(i < j ? i : j);
  306. }
  307.  
  308. max(i,j)  int i,j; 
  309. {
  310.         return(i > j ? i : j);
  311. }
  312.  
  313. notdone(board)  char *board; 
  314. {
  315.     return (board[1] || board[2] || board[3] || board[4]
  316.         || board[5] || board[6]) &&
  317.            (board[8] || board[9] || board[10] || board[11]
  318.         || board[12] || board[13]);
  319. }
  320.  
  321. countnodes(board,start) int start; char *board; 
  322. {
  323.         int i;
  324.         int num;
  325.         num = 0;
  326.     for (i = start; i< start + 6; ++i)
  327.         num += (board[i] ? 1 : 0);
  328.         return(num);
  329. }
  330.  
  331. incpit(board,pit) char *board; int pit; 
  332. {
  333.     display(1+holex[pit]+stonex[board[pit]],
  334.         3+holey[pit] +stoney[board[pit]]);
  335.     printf("\033F^\033G");
  336.     board[pit]++;
  337. }
  338.  
  339. display(x,y) int x,y; 
  340. {
  341.     printf("\033Y%c%c",x+32,y+32);
  342. }
  343.  
  344. decpit(board,pit) char *board; int pit; 
  345. {
  346.     board[pit]--;
  347.     display(1+holex[pit]+stonex[board[pit]],
  348.         3+holey[pit] +stoney[board[pit]]);
  349.     putchar(' ');
  350. }
  351.  
  352.  
  353. rpt(cc, n)
  354.  {    while (n--) printf(cc); }
  355.  
  356. rptc(cc, n)
  357.  {    while (n--) putchar(cc); }
  358.  
  359. nb1(n)
  360.  {    rpt("ii    q        p  q       p q       p q       p q       p q       p q       p  q        p  ii\n\r", n); }
  361.  
  362. NewBD()
  363.  {    printf("\033H\033J\033p\033F");
  364.     rptc('i', 77);
  365.     printf("\n\rii"); rptc(' ',73);
  366.     printf("ii\n\rii");
  367.     printf("       ME        6       5       4       3");
  368.     printf("       2       1               ii\n\rii    qr      _p ");
  369.     rpt(" qr     _p", 6); printf("            ii\n\r");
  370.     printf("ii    q        p  q       p q       p q       p q       p q       p q       p  qr      _p  ii\n\r");
  371.     nb1(2);
  372.     printf("ii    q        p  _q     pr _q     pr _q     pr _q     pr _q     pr _q     pr  q        p  ii\n\r");
  373.     printf("ii    q        p                                                   q        p  ii\n\r");
  374.  
  375.     printf("ii    q        p  qr     _p qr     _p qr     _p qr     _p qr     _p qr     _p  q        p  ii\n\r");
  376.     nb1(2);
  377.     printf("ii    _q      pr  q       p q       p q       p q       p q       p q       p  q        p  ii\n\r");
  378.     printf("ii              _q     pr _q     pr _q     pr _q     pr _q     pr _q     pr  _q      pr  ii\n\r");
  379.     printf("ii                 1       2       3       4       5       6        YOU    ii\n\r");
  380.     printf("ii                                                                         ii\n\r");
  381.     rptc('i', 77);
  382.     printf("\033G\033q");
  383.  }
  384.  
  385. sleep(n)
  386.  {    int i;
  387.     while (n--) for (i=6000; i--;); }
  388.  
  389. dmove(new,move) char *new,move; 
  390. {    int i;
  391.     int j; 
  392.     int who;
  393.     if ((move < 1) || (move > 13) || (move == 7) || !new[move])
  394.         printf("Bad arg to mmove: %d",move);
  395.     who = (move < 7 ? 1 : 0);
  396.     i = new[move];
  397.     for (j = 0; j < i; j++) decpit(new,move);
  398.     sleep(1);
  399.     while (i--) {
  400.         move = mod(move,who);
  401.         incpit(new,move);
  402. /*
  403.         putchar(7);
  404. */
  405.         sleep(1);
  406.     }
  407.     if (new[move] == 1 && who == (move < 7 ? 1 : 0) && move && move != 7)
  408.         while(new[14-move]) { 
  409.             decpit(new,14-move);
  410.             incpit(new,who*7);
  411.         }
  412.     if (move == 0 || move == 7) return(0); 
  413.     else return(1);
  414. }
  415.  
  416.  
  417. mmove(old,new,move) char *old;  char *new; int move; 
  418. {
  419.          int i; 
  420.         int who;
  421.         total++;
  422.  
  423.         for (i = 0; i < 14; ++i) new[i] = old[i];
  424.         if ((move < 1) || (move > 13) || (move == 7) || !new[move])
  425.                 printf("Bad arg to mmove: %d",move);
  426.         who = (move < 7 ? 1 : 0);
  427.         i = old[move];
  428.         new[move] = 0;
  429.         while (i--) {
  430.                 move = mod(move,who);
  431.         ++new[move];
  432.         }
  433.         if (new[move] == 1 && who == (move < 7 ? 1 : 0) && move && move != 7)
  434.         { 
  435.                 new[who*7] += new[14-move];
  436.                 new[14-move] = 0;
  437.         }
  438.         if (move == 0 || move == 7) return(0); 
  439.         else return(1);
  440. }
  441.